###################################################################### Product:      KnowledgeEngine (Plone Edition)## File:         Repository.py## Copyright:    Copyright (c) 2004, Faulkner Technologies## Author:       Brian Oliver## Description:  This file defines the Repository class, a simple#               'container' concepts for assessments and workflow.#   #               Use this as a base class for other specialised #               repositories.#               # See Also:     Element#####################################################################

####################################################################### Knowledge Engine Library Importsfrom Products.KnowledgeEngine.Common import *from Products.KnowledgeEngine.Core import *from Products.KnowledgeEngine.Element import Element, ElementInfofrom Products.KnowledgeEngine.PropertyDefinition import PropertyDefinitionfrom Products.KnowledgeEngine.EventDefinition import *from Products.KnowledgeEngine.Model.Model import Modelfrom Products.KnowledgeEngine.PermissionDefinition import *

####################################################################### Zope Library Importsfrom Globals import DTMLFilefrom ImageFile import ImageFile

####################################################################### Python Library Imports# (none)
####################################################################### RepositoryInfo Class Definitionclass RepositoryInfo(ElementInfo):    """        Defines the class info methods, defining information about        the class without needing an instance of the class    """        #---------------------------------------------------------------#        def getClassName(self):        """            Returns the name of the class for which             we are providing information.        """        return "Repository"

    #---------------------------------------------------------------#

    def getDisplayName(self):        """            Return a friendly name for the class instances            (this is used for displaying in lists etc)        """            return "Assessment Repository"            #---------------------------------------------------------------#

    def getIdentityType(self):        """            Return the identity type.          """                return "repo"            #---------------------------------------------------------------#        def getClassIcon(self):        """            Return the appropriate icon file for the class.        """                return ImageFile('skins/Repository_icon.gif', globals())

    #---------------------------------------------------------------#

    def isContainer(self):        """            Returns if the instance is providing folderish/container            services.                        Override an return true if the instance is to be            a container for other instances.                        NOTE: all instances support "events" so there is no            need to return true if you require "event" support.        """
        #Repositories are containers for reports!        return true            #---------------------------------------------------------------#

    def isPermittedInContainer(self, containerClassInfo, containerInstance = None, instance=None):        """            ABSTRACT: Returns if class instances (instance) is permitted in             the specified container (containerInstance)                        NOTE: This is from this class' instance perspective.        """                #DEFAULT RULE: Repositories are only permitted in Models        return containerClassInfo.isInstanceOf('Model') 

    #---------------------------------------------------------------#

    def isChildPermitted(self, childClassInfo, childInstance = None):        """            Returns if the specified child is permitted as a             child of the class' instances.                        NOTE: This is from this class' instance perspective.                        For component containers, this always overrides what the            return value from childClassInfo.isPermittedInContainer(...)        """                #DEFAULT RULE: Repositories may only contain Reports or Events        return childClassInfo.isInstanceOf('Report') or childClassInfo.isInstanceOf('Event')        #---------------------------------------------------------------#

    def onConfigureProperties(self):        """            Automatically called by the Knowledge Engine once            the class has been loaded.  Use this method to register             class specific properties using the PropertyReflection interface.                        If this class is sub-classed, a call must be made to            the super-class to ensure super-class properties are            correctly registered                        NOTE: This method is called before ClassInfo.onAfterStartup()                    """
        #initialise the super-class properties for reflection        ElementInfo.onConfigureProperties(self)        #---------------------------------------------------------------#

    def onConfigureEvents(self):        """            Automatically called by the Knowledge Engine once            the class has been loaded.  Use this method to register             class specific events using the EventReflection interface.                        If this class is sub-classed, a call must be made to            the super-class to ensure super-class properties are            correctly registered                        NOTE: This method is called before ClassInfo.onAfterStartup()                    """                        #initialise the super-class events for reflection        ElementInfo.onConfigureEvents(self)
        #add the onAfterAssessmentJoins event (which occurs after an assessment has joined the repository)        self.addEventDefinition(EventDefinition(identity="onAfterAssessmentJoins", \                                displayName="After Assessment joins the Repository", \                                description="Occurs after an assessment has joined the repository", \                                eventType=et_SERVER))
        #add the onBeforeAssessmentLeaves event (which occurs before an assessment leaves the repository)        self.addEventDefinition(EventDefinition(identity="onBeforeAssessmentLeaves", \                                displayName="Before Assessment leaves the Repository", \                                description="Occurs before an assessment leaves the repository", \                                eventType=et_SERVER))
        #add the onBeforeRemoveAssessmentFromRepository event (which occurs prior to an assessment being removed from the repository)        self.addEventDefinition(EventDefinition(identity="onBeforeRemoveAssessmentFromRepository", \                                displayName="Before Removing an Assessment from the repository", \                                description="Occurs before an assessment is removed from the repository", \                                eventType=et_SERVER))
        #add the onBeforeSaveAssessmentInRepository event (which occurs prior to an assessment that exists in this repository being saved)        self.addEventDefinition(EventDefinition(identity="onBeforeSaveAssessmentInRepository", \                                displayName="Before Saving an Assessment that exists in the repository", \                                description="Occurs before an Assessment (that exists in the repository) is saved.  Should the Assessment exist in other repositories, the equivalent event will be raised for those repositories as well.", \                                eventType=et_SERVER))
        #add the onBeforeSaveAssessmentForLaterInRepository event (which occurs prior to an assessment that exists in this repository being saved 'for later')
        self.addEventDefinition(EventDefinition(identity="onBeforeSaveAssessmentForLaterInRepository", \
                                displayName="Before Saving an Assessment that exists in the repository (for later)", \
                                description="Occurs before an Assessment (that exists in the repository) is saved (for later).  Should the Assessment exist in other repositories, the equivalent event will be raised for those repositories as well.", \
                                eventType=et_SERVER))
        #add the onBeforeSubmitAssessmentInRepository event (which occurs prior to an assessment that exists in this repository being submitted)        self.addEventDefinition(EventDefinition(identity="onBeforeSubmitAssessmentInRepository", \                                displayName="Before Submitting an Assessment that exists in the repository", \                                description="Occurs before an Assessment (that exists in the repository) is submitted.  Should the Assessment exist in other repositories, the equivalent event will be raised for those repositories as well.", \                                eventType=et_SERVER))
        #add the onBeforeSubmitAssessmentFromRepository event (which occurs prior to an assessment being submitted that was opened from the repository)        self.addEventDefinition(EventDefinition(identity="onBeforeSubmitAssessmentFromRepository", \                                displayName="Before Submitting an Assessment opened from the repository", \                                description="Occurs before an Assessment is submitted that was originally opened from the repository", \                                eventType=et_SERVER))        #---------------------------------------------------------------#

    def onConfigurePermissions(self):        """            Automatically called by the Knowledge Engine once            the class has been loaded.  Use this method to register             class specific permission definitions.                        If this class is sub-classed, a call must be made to            the super-class to ensure super-class properties are            correctly registered                        NOTE: This method is called before ClassInfo.onAfterStartup()                    """
        #initialise the super-class permissions for reflection        ElementInfo.onConfigurePermissions(self)
        
        #add a definition for the 'AccessRepositoryWithPersonalAssessments' permission        self.addPermissionDefinition(PermissionDefinition(identity="AccessRepository", displayName="Access Repository", description="Permission to access a Repository", securableScope=SS_ALL, actorScope=AS_ALL, usesCredits=false, isCommencementPermitted=true, isExpiryPermitted=true, usesAssessmentScope=true))
                #add a definition for the 'AssessWithinRepository' permission        self.addPermissionDefinition(PermissionDefinition(identity="EditRepositoryAssessments", displayName="Edit Repository Assessments", description="Permission to open, edit and update <b>accessible</b> repository assessments", securableScope=SS_ALL, actorScope=AS_ALL, usesCredits=false, isCommencementPermitted=true, isExpiryPermitted=true))
                #add a definition for the 'RenameRepositoryAssessments' permission        self.addPermissionDefinition(PermissionDefinition(identity="RenameRepositoryAssessments", displayName="Rename Repository Assessments", description="Permission to rename <b>accessible</b> repository assessments", securableScope=SS_ALL, actorScope=AS_ALL, usesCredits=false, isCommencementPermitted=true, isExpiryPermitted=true))                #add a definition for the 'RemoveRepositoryAssessments' permission        self.addPermissionDefinition(PermissionDefinition(identity="RemoveRepositoryAssessments", displayName="Remove Repository Assessments", description="Permission to remove <b>accessible</b> repository assessments", securableScope=SS_ALL, actorScope=AS_ALL, usesCredits=false, isCommencementPermitted=true, isExpiryPermitted=true))

    #---------------------------------------------------------------#

####################################################################### Repository Class Definitionclass Repository(Element):    """        A class to represent an assessment repository    """

    #---------------------------------------------------------------#
    #ABSTRACT TRANSIENT: a ClassInfo implementation instance to provide info about this class    _CLASSINFO = RepositoryInfo()

    #---------------------------------------------------------------#    # Volatile Attributes    _v_Model = None             #the model to which the repository belongs

    #---------------------------------------------------------------#

    def __init__(self, id, identity):        "Constructor for the Repository"        
        Element.__init__(self, id, identity)                #perform onAfterInstanciation processing        self.onAfterInstanciation()

    #---------------------------------------------------------------#

    def onAfterInstanciation(self):        """            Handle Knowledge Engine specific actions after this object             has been loaded into memory.                          This is useful for performing backwards compatibility        """                        #perform default processing        Element.onAfterInstanciation(self)

    #---------------------------------------------------------------#

    def getModel(self):        """            Returns the Model in which this repository is located.        """
        #have we already worked out the model        if self._v_Model == None:
            #get the parent of this component            parent = self.getParent()
            #is the parent a Model?            if isinstance(parent, Model):                self._v_Model = parent
            else:                self._v_Model = parent.getModel()
        #returned the cached model        return self._v_Model                    #---------------------------------------------------------------#

    def isDisplayedBeforeComponents(self):        """            Returns if the Element is to be displayed before            components in a model. Alternatively the Element is            displayed after the components in a model.            (If the element is in a model)        """                #Repositorys are displayed before         return false

    #---------------------------------------------------------------#

    def onBeforeDelete(self):        """            Handle Knowledge Engine specific actions before repository is deleted            (like cleaning up assessments that are in the repository)        """                #get the assessment storage service (so we can remove assessments from the repository)        assessmentStorageService = self.getModel().getAssessmentStorageService()                #remove the assessments from this repository        assessmentStorageService.removeAssessmentsFromRepository(self.getModel(), self.getIdentity())
        #perform normal onBeforeDelete processing        Element.onBeforeDelete(self)

    #---------------------------------------------------------------#

    def getModel(self):        """            Returns the Model in which this repository is located.        """
        parent = self.getParent()                while not parent.isInstanceOf("Model"):            parent = parent.getParent()    
        return parent

    #---------------------------------------------------------------#

    def getReports(self, user = None, className = None):        """            Returns a sequence of the immediate child Report(s)            in this container, sorted by title. If className is specified            then the results are filtered.                        When a user is specified, 'view report' permissions are             checked for each report - only reports with granted            view permissions are returned.                        NOTE: does not return reports in other components (ie: repositories)        """
        #get the immediate children of the container        children = self.objectValues()
        #filter the Report(s) only        reports = [x for x in children if x.isInstanceOf("Report")]                #filter the specific classes of reports        if className != None:            reports = [x for x in reports if x.isInstanceOf(className)]                #filter based on user permissions (if a user was provided)        if user is not None:            #grab the security service so we can check some permissions            securityService = getSecurityService(self)
            #grab the credit management service so we can check credits            creditManagementService = getCreditManagementService(self)                        #determine the permitted reports            permittedReports = []            for report in reports:                                #get the permission for the current report                    permission = securityService.getEffectivePermission("ViewReport", report.getIdentity(), user.getIdentity())                                #is the current report permitted?                if permission is not None and permission.granted() and creditManagementService.getEffectiveCredits(permission, report, user) != 0:                    permittedReports = permittedReports + [report]
            #set the resulting permitted reports            reports = permittedReports                                            #sort the report by Report.getTitle()        reports.sort(lambda x, y : x.getTitle() < y.getTitle())
        return reports                                #---------------------------------------------------------------#

####################################################################### Class Initialisation
# Register Class Information with the Knowledge EngineregisterGenericObjectClass(Repository)
#####################################################################
